﻿using System;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameName1
{
    sealed class GameplayScene : GameScene
    {
        public static int Points;
        public static int Lives = 3;

        public static GameState GameState { private get; set; }

        private GameObjectsManager _gameObjectsManager = GameObjectsManager.GetInstance();

        private Texture2D _backgroundSprite;
        private Texture2D _barSprite;
        private Texture2D _spaceShipSprite;
              
        private SpriteFont _font;
        
        public GameplayScene()
        {
            Points = 0;
            Lives = 3;
            
            LoadContent();

            AngryAlienController.MoveDelay = 1050;
            AngryAlien.FireRate = 550;

            GameObjectsManager.GetInstance().DestroyAll();
            GameObjectsManager.GetInstance().Instantiate(new AngryAlienController());
            GameObjectsManager.GetInstance().Instantiate(new PowerUpController());
            GameObjectsManager.GetInstance().Instantiate(new BonusAlienController());
            SpawnSpaceShip();

            GameState = new GameStateSpawningAngryAliens();           
        }

        private void SpawnSpaceShip()
        {
            var spaceShip = new SpaceShip(new Vector2(400, 550));
           
            var weapon = new RocketLauncher(-1) {ReloadTime = 250};
            spaceShip.Weapon = weapon;

            _gameObjectsManager.Instantiate(spaceShip);
        }
        
        public override void LoadContent()
        {            
            base.LoadContent();
            _spaceShipSprite = ContentManager.Load<Texture2D>("Sprites/player.png");
            _backgroundSprite = ContentManager.Load<Texture2D>("sprites/background");
            _barSprite = ContentManager.Load<Texture2D>("sprites/bar");

            _font = ContentManager.Load<SpriteFont>("myFont");        

            var types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (var type in types)
            {
                if (type.IsSubclassOf(typeof(GameObject)))
                {
                    var methodInfo = type.GetMethod("LoadContent"); 
                    if(methodInfo!=null) methodInfo.Invoke(null,new object[] {ContentManager});
                }
            }         
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
            ContentManager.Unload();
        }

        public override void Update(GameTime gameTime)
        {
            GameState.Update(this,gameTime);
        }

        internal void UpdateObjects(GameTime gameTime)
        {
            _gameObjectsManager.GetAllObjectsOfType<GameObject>().ForEach(o => o.Update(gameTime));          
        }
        internal void CheckCollision(GameTime gameTime)
        {
            var hittableObjects = _gameObjectsManager.GetAllObjectsOfType<IHittable>();
            for (var i = 0; i < hittableObjects.Count; i++)
            {
                for (var j = i + 1; j < hittableObjects.Count; j++)
                {
                    if ((hittableObjects[i].GetCollisionBox().Intersects(hittableObjects[j].GetCollisionBox())))
                    {
                        if (!hittableObjects[i].GetNotHittableTypes().Any(type => type.IsInstanceOfType(hittableObjects[j]))) hittableObjects[i].HandleHit(hittableObjects[j], gameTime);
                        if (!hittableObjects[j].GetNotHittableTypes().Any(type => type.IsInstanceOfType(hittableObjects[i]))) hittableObjects[j].HandleHit(hittableObjects[i], gameTime);     
                    }
                }
            }
        }
        internal void DestroyByBoundary()
        {
            var boundary = new Rectangle(-100, 50, 900, 500);
            foreach (var hittableObject in _gameObjectsManager.GetAllObjectsOfType<IHittable>())
            {
                if (hittableObject is SpaceShip) continue;
                if (!hittableObject.GetCollisionBox().Intersects(boundary))
                {
                    hittableObject.HandleHit(null,null);                   
                }
            }
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            DrawBackground(spriteBatch);
            DrawGameObjects(spriteBatch);

            DisplayScore(spriteBatch);
            DisplayShields(spriteBatch);
        }

        private void DrawBackground(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(_backgroundSprite, new Vector2(0, 0), Color.White);
            spriteBatch.Draw(_barSprite, new Vector2(20, ScreenManager.GetInstance().Resolution.Y - 15));
        }
        private void DrawGameObjects(SpriteBatch spriteBatch)
        {
            var displayableObjects = _gameObjectsManager.GetAllObjectsOfType<IDisplayable>().OrderBy(o => o.DrawingOrder).ToList();
            foreach (var displayableObject in displayableObjects)
            {
                displayableObject.Draw(spriteBatch);
            }
        }
        private void DisplayScore(SpriteBatch spriteBatch)
        {
            spriteBatch.DrawString(_font, "SCORE:", new Vector2(5, 5), Color.White);
            spriteBatch.DrawString(_font, Points.ToString(), new Vector2(85, 5), new Color(0, 255, 0));
        }
        private void DisplayShields(SpriteBatch spriteBatch)
        {
            spriteBatch.DrawString(_font, "LIVES:", new Vector2(575, 5), Color.White);
            for (int i = 0; i < Lives; i++)
                spriteBatch.Draw(_spaceShipSprite, new Vector2(600 + ((i + 1) * 50), 3), Color.White);
        }               
    }
}
